package com.jfinal.utils;

import de.odysseus.staxon.json.JsonXMLConfig;
import de.odysseus.staxon.json.JsonXMLConfigBuilder;
import de.odysseus.staxon.json.JsonXMLInputFactory;
import de.odysseus.staxon.json.JsonXMLOutputFactory;
import de.odysseus.staxon.xml.util.PrettyXMLEventWriter;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import javax.servlet.http.HttpServletRequest;
import javax.xml.stream.*;
import java.io.InputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.*;

/**
 * @author LarryKoo(larrykoo@126.com)
 * @date 2015-12-13
 */
public class Xml2StringKit {
    /**
     * 解析微信发来的请求（XML）
     *
     * @param request
     * @return Map<String,String>
     * @throws Exception
     * @throws
     */
    public static Map<String, Object> parseXml2Map(HttpServletRequest request) {
        // 将解析结果存储在HashMap中
        Map<String, Object> map = new HashMap<>();
        // 从request中取得输入流, 使用JDK7 try-with-resources
        try (InputStream inputStream = request.getInputStream()) {
            // 读取输入流
            SAXReader reader = new SAXReader();
            Document document = reader.read(inputStream);
            // 得到xml根元素
            Element root = document.getRootElement();
            // 得到根元素的所有子节点
            List<Element> elementList = root.elements();

            // 遍历所有子节点
            for (Element e : elementList) {
                map.put(e.getName(), e.getData());
            }
            return map;
        } catch (Exception e) {
            throw Exceptions.unchecked(e);
        }
    }

    /**
     * 转换request中的XML数据为String字符串XML文本
     *
     * @param request
     * @return
     */
    public static String parseXmlStr(HttpServletRequest request) {
        String res = "";
        // 从request中取得输入流, 使用JDK7 try-with-resources
        try (InputStream inputStream = request.getInputStream()) {
            // 读取输入流
            SAXReader reader = new SAXReader();
            Document document = reader.read(inputStream);
            res = document.asXML();
            return res;
        } catch (Exception e) {
            throw Exceptions.unchecked(e);
        }
    }


    /**
     * json string string convert to xml
     *
     * @param json
     * @return
     */
    public static String json2xml(String json) {
        XMLEventReader reader = null;
        XMLEventWriter writer = null;
        JsonXMLConfig config = new JsonXMLConfigBuilder().multiplePI(false).repairingNamespaces(false).build();
        try (StringReader input = new StringReader(json);
             StringWriter output = new StringWriter()) {

            reader = new JsonXMLInputFactory(config).createXMLEventReader(input);
            writer = XMLOutputFactory.newInstance().createXMLEventWriter(output);
            writer = new PrettyXMLEventWriter(writer);
            writer.add(reader);

            if (output.toString().length() >= 38) {//remove <?xml version="1.0" encoding="UTF-8"?>
                return output.toString().substring(39);
            }
            return output.toString();
        } catch (Exception e) {
            throw Exceptions.unchecked(e);
        } finally {
            try {
                reader.close();
                writer.close();
            } catch (XMLStreamException e) {
                throw Exceptions.unchecked(e);
            }
        }
    }

    /**
     * xml string convert to json string
     *
     * @param xml
     * @return
     */
    public static String xml2json(String xml) {
        XMLEventReader reader = null;
        XMLEventWriter writer = null;

        JsonXMLConfig config = new JsonXMLConfigBuilder().autoArray(true).autoPrimitive(true).prettyPrint(true).build();
        try (StringReader input = new StringReader(xml);
             StringWriter output = new StringWriter()) {

            reader = XMLInputFactory.newInstance().createXMLEventReader(input);
            writer = new JsonXMLOutputFactory(config).createXMLEventWriter(output);
            writer.add(reader);

            return output.toString();
        } catch (Exception e) {
            throw Exceptions.unchecked(e);
        } finally {
            try {
                reader.close();
                writer.close();
            } catch (XMLStreamException e) {
                throw Exceptions.unchecked(e);
            }
        }
    }

    /**
     * 把数组所有元素排序，并按照“参数=参数值”的模式用“&”字符拼接成字符串
     *
     * @param params 需要排序并参与字符拼接的参数组
     * @return 拼接后字符串
     */
    public static String parseLinkString(Map<String, String> params) {
        List<String> keys = new ArrayList<>(params.keySet());
        Collections.sort(keys);
        String preStr = "";
        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            String value = params.get(key);
            if (i == keys.size() - 1) {             //拼接时，不包括最后一个&字符
                preStr = preStr + key + "=" + value;
            } else {
                preStr = preStr + key + "=" + value + "&";
            }
        }
        return preStr;
    }

}
